---
title: "Linux命令 - sed"
categories:
- linux
tags:
---

<div id="content">
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#org2d23f93">一般用法：</a></li>
<li><a href="#orge22c914">Snippets</a>
<ul>
<li><a href="#org2e877e1">Find and append to end of line</a></li>
</ul>
</li>
<li><a href="#orgad369d0">命令行选项</a>
<ul>
<li><a href="#org69209dd">–version</a></li>
<li><a href="#orgaa27efc">–help</a></li>
</ul>
</li>
<li><a href="#org23be860">SCRIPT</a>
<ul>
<li><a href="#org64d41b0">Address （Script格式的[addr]部分）</a>
<ul>
<li><a href="#orga36d0f1">数字</a></li>
<li><a href="#orge97a544">正则</a></li>
<li><a href="#orge1acf8e">范围</a></li>
<li><a href="#orge71900f">反向操作：'!'</a></li>
</ul>
</li>
<li><a href="#org5215676">Command （Script格式的X部分）</a>
<ul>
<li><a href="#org26f2ab4">a</a></li>
<li><a href="#org27143b1">c</a></li>
<li><a href="#org873f429">d</a></li>
<li><a href="#orgb96df29">i</a></li>
<li><a href="#orgba8405d">p</a></li>
<li><a href="#org683110d">s</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="outline-2" id="outline-container-org2d23f93">
<h2 id="org2d23f93">一般用法：</h2>
<div class="outline-text-2" id="text-org2d23f93">
<p>
{% raw %} sed SCRIPT INPUTFILE... {% endraw %}
</p>
<p>
例如替换所有的hello为world： {% raw %} sed 's/hello/world/' input.txt &gt; output.txt {% endraw %} 。
这条命令不会修改文件input.txt的内容，因此将更改后的内容重定向到output.txt中。
如果不指定INPUTFILE，或INPUTFILE是'-'，sed从stdin中读取数据。
</p>
<p>
下面几条命令是相同的：
</p>
<p>
sed 's/hello/world/' input.txt &gt; output.txt
sed 's/hello/world/' &lt; input.txt &gt; output.txt
cat input.txt | sed 's/hello/world/' - &gt; output.txt
</p>
<p>
sed将结果写到stdout。使用'-i'直接更改文件。还有'W'和's///w'命令，将修改后的结果到其他文件。
下面的命令修改文件file.txt，并且不会输入任何结果：
</p>
<p>
sed -i 's/hello/world' file.txt
</p>
<p>
使用'-p'命令输出指定的行。例如下面的命令输出第45行：
</p>
<p>
sed -n '45p' file.txt
</p>
<p>
sed将多个文件作为一个对待。下面的命令输出第一个文件的第一行和最后一个文件的最后一行。使用'-s'能够让这种行为反过来。
</p>
<p>
sed -n  '1p ; $p' one.txt two.txt three.txt
</p>
<p>
使用'-e'或'-f'时，sed将第一个非选项参数作为要执行的脚本，然后将接下来的非选项参数作为输入文件。
如果'-e'或'-f'时，所有的非选项参数都被作为输入文件。
'-e'和'-f'能够一起使用，也能出现多次。(in which case the final effective SCRIPT will be concatenation of all the individual SCRIPTs).
</p>
<p>
下面的命令是等价的：
</p>
<p>
sed 's/hello/world/' input.txt &gt; output.txt
</p>
<p>
sed -e 's/hello/world/' input.txt &gt; output.txt
sed –expression='s/hello/world/' input.txt &gt; output.txt
</p>
<p>
echo 's/hello/world/' &gt; myscript.sed
sed -f myscript.sed input.txt &gt; output.txt
sed –file=myscript.sed input.txt &gt; output.txt
</p>
</div>
</div>
<div class="outline-2" id="outline-container-orge22c914">
<h2 id="orge22c914">Snippets</h2>
<div class="outline-text-2" id="text-orge22c914">
</div>
<div class="outline-3" id="outline-container-org2e877e1">
<h3 id="org2e877e1">Find and append to end of line</h3>
<div class="outline-text-3" id="text-org2e877e1">
<div class="org-src-container">
<pre class="src src-sh">sed <span style="font-style: italic;">'/Fred Flintstone/ s/$/ ***/'</span> filename
</pre>
</div>
<p>
查找Fred Flintstone，然后在行尾追加"&lt;space&gt;***", <i>Fred Flintstone</i> 表示查找，s开始为替换，$表示行尾
</p>
</div>
</div>
</div>
<div class="outline-2" id="outline-container-orgad369d0">
<h2 id="orgad369d0">命令行选项</h2>
<div class="outline-text-2" id="text-orgad369d0">
<p>
sed OPTIONS… [SCRIPT] [INPUTFILE…]
</p>
</div>
<div class="outline-3" id="outline-container-org69209dd">
<h3 id="org69209dd">–version</h3>
</div>
<div class="outline-3" id="outline-container-orgaa27efc">
<h3 id="orgaa27efc">–help</h3>
</div>
</div>
<div class="outline-2" id="outline-container-org23be860">
<h2 id="org23be860">SCRIPT</h2>
<div class="outline-text-2" id="text-org23be860">
<p>
'sed' 脚本的格式如下：
</p>
<p>
{% raw %} [addr]X[options] {% endraw %}
</p>
<p>
其中，addr optional，表示行地址，能够使用数字、正则、范围表示；X是单个字符，表示command；options是command需要的。
例如 {% raw %} sed '30,35d' input.txt &gt; output.txt {% endraw %} 删除30到35行：
</p>
</div>
<div class="outline-3" id="outline-container-org64d41b0">
<h3 id="org64d41b0">Address （Script格式的[addr]部分）</h3>
<div class="outline-text-3" id="text-org64d41b0">
<p>
Address用于指定在哪些行sed，行是从1开始的。
如果没有指定addr，则应用于所有的行。
</p>
</div>
<div class="outline-4" id="outline-container-orga36d0f1">
<h4 id="orga36d0f1">数字</h4>
<div class="outline-text-4" id="text-orga36d0f1">
<p>
例如： {% raw %} sed '144s/hello/world/' input.txt &gt; output.txt {% endraw %} 在第144行上执行查找替换操作。
</p>
</div>
</div>
<div class="outline-4" id="outline-container-orge97a544">
<h4 id="orge97a544">正则</h4>
<div class="outline-text-4" id="text-orge97a544">
<p>
例如： {% raw %} sed '/apple/s/hello/world' input.txt &gt; output.txt {% endraw %} 在包含apple的行上执行后面的 s/hello/world 操作。
</p>
</div>
</div>
<div class="outline-4" id="outline-container-orge1acf8e">
<h4 id="orge1acf8e">范围</h4>
<div class="outline-text-4" id="text-orge1acf8e">
<p>
使用','分隔两个addr，两个addr能够是数字，也能是正则，甚至是混合的。
例如： {% raw %} sed '4,17s/hello/world' input.txt &gt; output.txt {% endraw %} 在4到17行（包含17行）上执行后面的 s/hello/world 操作。
</p>
</div>
</div>
<div class="outline-4" id="outline-container-orge71900f">
<h4 id="orge71900f">反向操作：'!'</h4>
<div class="outline-text-4" id="text-orge71900f">
<p>
addr部分，X部分前面，加上'!'符号，对addr取反。
例如： {% raw %} sed '/apple/!s/hello/world/' input.txt &gt; output.txt {% endraw %} 在 <b>不</b> 包含apple的行上执行后面的 s/hello/world 操作。
例如： {% raw %} sed '4,17!s/hello/world/' input.txt &gt; output.txt {% endraw %} 仅在1~3和18到结尾的行上执行后面的 s/hello/world 操作。
</p>
</div>
</div>
</div>
<div class="outline-3" id="outline-container-org5215676">
<h3 id="org5215676">Command （Script格式的X部分）</h3>
<div class="outline-text-3" id="text-org5215676">
<p>
下面是sed支持的命令，一些是POSIX标准，还有些是GNU扩展的。
</p>
</div>
<div class="outline-4" id="outline-container-org26f2ab4">
<h4 id="org26f2ab4">a</h4>
<div class="outline-text-4" id="text-org26f2ab4">
<p>
追加行。例如：
</p>
<pre class="example">
$ echo "old
old
old
old" | sed '1a new_line'
# OUTPUT
old
new_line
old
old
old

$ echo "old
old
old
old" | sed '1,2a new_line'
# OUTPUT 1到2行，每一行的后面都追加了新行
old
new_line
old
new_line
old
old
</pre>
</div>
</div>
<div class="outline-4" id="outline-container-org27143b1">
<h4 id="org27143b1">c</h4>
<div class="outline-text-4" id="text-org27143b1">
<p>
替换行，例如：
</p>
<pre class="example">
$ echo "old
old
old
old" | sed '1,2c new_line'
# OUTPUT sed指定了两行，两行被替换成了new_line，是的，结果是相比原来少了一行，而 *不是分别* 将1和2行替换成new_line
new_line
old
old
</pre>
</div>
</div>
<div class="outline-4" id="outline-container-org873f429">
<h4 id="org873f429">d</h4>
<div class="outline-text-4" id="text-org873f429">
<p>
删除行，例如 {% raw %} sed '3d' input.txt {% endraw %}
</p>
</div>
</div>
<div class="outline-4" id="outline-container-orgb96df29">
<h4 id="orgb96df29">i</h4>
<div class="outline-text-4" id="text-orgb96df29">
<p>
插入。在指定行之前插入新的行。'a'是在指定行之后，'i'是在指定行前。
</p>
</div>
</div>
<div class="outline-4" id="outline-container-orgba8405d">
<h4 id="orgba8405d">p</h4>
<div class="outline-text-4" id="text-orgba8405d">
<p>
打印，结合addr使用，能够实现查询（由于addr支持正则）
</p>
</div>
</div>
<div class="outline-4" id="outline-container-org683110d">
<h4 id="org683110d">s</h4>
<div class="outline-text-4" id="text-org683110d">
<p>
查找替换，它的语法是 {% raw %} s/REGEXP/REPLACEMENT/FLAGS {% endraw %} 。查找匹配REGEXP（正则）的部分，然后替换为REPLACEMENT。类似vim中的。
</p>
<p>
FLAGS部分：
</p>
</div>
<ul class="org-ul">
<li><a id="org8818f55"></a>g<br/>
<div class="outline-text-5" id="text-org8818f55">
<p>
替换所有匹配，例如： {% raw %} sed 's/old/new/g' {% endraw %}
</p>
</div>
</li>
<li><a id="orgfa4cf28"></a>NUMBER<br/>
<div class="outline-text-5" id="text-orgfa4cf28">
<p>
FLAGS是一个数字，表示查找替换的次数。
例如： {% raw %} sed 's/old/new/3' {% endraw %}
</p>
<p>
POSIX标准没有规定g和NUMBER一同使用应该怎样，在GNU的sed中是：忽略NUMBER次这前的，然后到结尾，NUMBER相当于起点。
例如 {% raw %} sed 's/old/new/g3' {% endraw %} 。下面是 <a href="https://unix.stackexchange.com/questions/155805/sed-replace-first-k-instances-of-a-word-in-the-file">SO</a> 上的例子，只替换前几个匹配的：
</p>
<pre class="example">
$ echo old old old old old | sed -E 's/\&lt;old\&gt;/\n/g4; s/\&lt;old\&gt;/new/g; s/\n/old/g'
# OUTPUT
# new new new old old
# 由于g和NUMBER是忽略，所以上面的脚本做了：
# 1. s/old/\n/g4 忽略4个匹配以前的， =&gt; old old old \n \n
# 2. s/old/new/g old替换为new =&gt; new new new \n \n
# 3. s/\n/old/g \n换回old =&gt; new new new old old
</pre>
</div>
</li>
<li><a id="orgbb11bfe"></a>w FILENAME<br/>
<div class="outline-text-5" id="text-orgbb11bfe">
<p>
将结果写入指定的文件。GNU扩展了两FILENAME：stdout stderr
</p>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="status" id="postamble">
<p class="author">Author: gdme1320</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
